<?php
defined('CORE') or exit('Request Error!');

/**
 * pub_filter
 * 
 * @author lane<61647649@qq.com> 
 */
class pub_filter
{ 

    //过滤类型
    protected $_filter_types = array(
        'int',         //0-12位的数字(可包含-)
        'float',       //小数
        'email',       //邮箱
        'qq',          //5-12位数字 (不匹配返回0)
        'mobile',      //11位数字   (不匹配返回0)
        'ip',          //用户ip
        'username',    //用户名 长度5-15，只允许0-9, a-z, _ 不能以_开头，必须包含字母
        'password',    //用户密码 长度6-20
        'var',         //变量名类型，即是 \w （0-9 a-z A-Z）
        'keyword',     //搜索关键字（对一些特殊字符进行过滤）只能含有 中文，0-9， a-z  _ # : @ . + - tab, 其他全部过滤，只能最长30
        'text',        //提交备注，问题

        'mac',         // 手机网卡:
        'imei',        // 手机IMEI
        'phone_type',  // 机型
        'screen',      // 分辨率
        'os',          // 手机系统， android ios other
        'version',     // 版本号
        'net',         // 2G, 3G, 4G, WIFI, other
        'operators',   // 'china_mobile', 'china_unicom', 'china_telecom', 'other'
        'location',    // 坐标
        'platform',    // 平台 android ，normal_ios, piracy_ios, other 
    );

    /**
     * 过滤操作
     * @param $val   变量值
     * @param $type  当type为数字的时候，表示截取指定长度的字符
     * @param $throw_error 是否抛出异常(只对邮箱、用户名、qq、手机类型有效)，如果不抛出异常，会对无效的数据设置为空
     *                     (此值用户不直接使用，一般通过 req::$throw_error 进行设置)
     * @return void
     */
    public static function filter(&$val, $type = '', $throw_error=false)
    {
        // 没指定过滤类型或变量为数组，不处理
        if( $type == '' || is_array($val) ) 
        {
            return;
        }

        $type = strtolower( $type );
        //$val  = trim( strtolower($val) );
        $val  = trim( $val );

        switch( $type )
        {
            case 'int':
                if (preg_match("#[^0-9]+#i", $val))
                {
                    $val = "";
                }
                $val = intval($val);
                break;
            case 'float':
                $val = preg_replace("/[^0-9xa-fA-F\.\-]/", '', $val);
                $val = floatval( $val );
                break;
            case 'email':
                if( !self::_test_email($val) )
                {
                    if( $val > 0 && $throw_error ) 
                        self::_throw_errmsg( "Email不合法" );
                    else
                        $val = '';
                }
                break;
            case 'username':
                $val = strtolower($val);
                if( !self::_test_user_name($val) )
                {
                    if( $throw_error ) 
                        self::_throw_errmsg( "用户名不合法" );
                    else 
                        $val = '';
                }
                break;
            case 'password':
                if( strlen($val) < 6 || strlen($val) > 20 )
                {
                    if( $throw_error ) 
                        self::_throw_errmsg( "用户密码不合法" );
                    else 
                        $val = '';
                }
                break;
            case 'qq':
                $val = preg_replace("/[^0-9]/i", '', $val);
                if( strlen($val) < 5 )
                {
                    if( $val > 0 && $throw_error ) 
                        self::_throw_errmsg( "QQ号码不合法" );
                    else 
                        $val = '';
                }
                break;
            case 'phone':
                $val = preg_replace("/[^0-9]/", '', $val);
                if( !preg_match("/^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|7[0678])\d{8}$/", $val) )
                {
                    if( $throw_error )
                        self::_throw_errmsg( "手机号码不合法" );
                    else
                        $val = '';
                }
                break;
            case 'ip':
                if( !self::_test_ip($val) ) 
                    $val = '';
                break;
            case 'var':
                // 过滤掉除了大小写字母,数字之外所有的字符
                $val = preg_replace("/[^\w]/", '', $val);
                break;
            case 'keyword':
                $val = self::_filter_keyword($val);
                $val = util::utf8_substr($val, 30);
                break;
            case 'text':
                $val = self::_filter_keyword($val);
                break;
            case 'mac':
                if (!self::_filter_mac($val))
                    $val = '';
                break;
            case 'imei':
                if (!self::_filter_imei($val))
                    $val = '';
                break;
            case 'phone_type':
                if (!self::_filter_phone_type($val))
                    $val = '';
                break;
            case 'screen':
                if (!self::_filter_screen($val))
                    $val = '';
                break;
            case 'os':
                if (!self::_filter_os($val))
                    $val = '';
                break;
            case 'version':
                if (!self::_filter_version($val))
                    $val = '';
                break;
            case 'net':
                if (!self::_filter_net($val))
                    $val = '';
                break;
            case 'operators':
                if (!self::_filter_operators($val))
                    $val = '';
                break;
            case 'location':
                if (!self::_filter_location($val))
                    $val = '';
                break;
            case 'platform':
                if (!self::_filter_platform($val))
                    $val = '';
                break;
            default:
                $val = "";
                break;
        }
    }

    /**
     * _filter_mac 过滤mac地址
     * 
     * @param string $val
     * @static 
     * @return string
     */
    private static function _filter_mac($val)
    {
        return preg_match("#^([0-9a-z]{2}):([0-9a-z]{2}):([0-9a-z]{2}):([0-9a-z]{2}):([0-9a-z]{2}):([0-9a-z]{2})$#i", $val);
    }

    /**
     * _filter_imei 过滤imei
     * 
     * @param mixed $val android 16位  ios: 36位 格式: 07C87DF4-01CD-4CD0-9FA4-097777E8E1DE
     * @static 
     * @return void
     */
    private static function _filter_imei($val)
    {
        return preg_match("#^([0-9a-zA-Z]{8})-([0-9a-zA-Z]{4})-([0-9a-zA-Z]{4})-([0-9a-zA-Z]{4})-([0-9a-zA-Z]{12})$#i", $val)
            || preg_match("#^[0-9a-zA-Z]{15}$#i", $val);
    }

    /**
     * _filter_phone_type 过滤机型, 长度不会超过10
     * 
     * @param string $val
     * @return void
     */
    private static function _filter_phone_type($val)
    {
        return strlen($val) > 10;
    }

    /**
     * _filter_screen 过滤分辨率 格式 1231*1231
     * 
     * @param string $val
     * @return void
     */
    private static function _filter_screen($val)
    {
        return preg_match("#^([0-9]{1,4})\*([0-9]{1,4})$#i", $val);
    }

    private static function _filter_os($val)
    {
        $data = array('android', 'ios', 'other');
        return in_array($val, $data);
    }

    private static function _filter_version($val)
    {
        return preg_match("#^[0-9]+\.*[0-9]*$#i", $val) && strlen($val) <= 5;
    }

    private static function _filter_net($val)
    {
        $data = array("2g", '3g', '4g', 'wifi', 'other');
        return in_array($val, $data);
    }

    private static function _filter_operators($val)
    {
        $data = array('china_mobile', 'china_unicom', 'china_telecom', 'other');
        return in_array($val, $data);
    }

    private static function _filter_location($val)
    {
        return preg_match("#^([0-9]+\.[0-9]+),([0-9]+\.[0-9]+)$#i", $val);
    }

    private static function _filter_platform($val)
    {
        $data = array('android', 'normal_ios', 'piracy_ios', 'other');
        return in_array($val, $data);
    }

    /**
     * 检测用户名 长度5-15，只允许0-9, a-z, _ 不能以_开头，必须包含字母
     * @param string $user_name
     * @return bool
     */
    private static function _test_user_name($user_name)
    {
        return preg_match('/^[a-z0-9]+[_a-z0-9]+$/iu', $user_name) 
            && strlen($user_name) >= 5 && strlen($user_name) <= 15 
            && preg_match('/[a-z]/iu', $user_name);
    }

    /**
     * 替换关键字非法字符（允许空格和个别特殊符号）
     * 只能含有 中文，0-9， a-z A-Z  _ # : @ . , + - tab [ ] % \n, 其他全部过滤
     * 中文标点： 。 ；  ， ： “ ”（ ） 、 ？ 《 》
     * @param string $keyword
     * @return bool
     */
    private static function _filter_keyword($val)
    {
        return preg_replace('/[^a-zA-Z0-9\x{4e00}-\x{9fa5}\x{3002}\x{ff1b}\x{ff0c}\x{ff1a}\x{201c}\x{201d}\x{ff08}\x{ff09}\x{3001}\x{ff1f}\x{300a}\x{300b} _#:@\.,\t\+\-\[\]%\n]/iu', '', $val);
    }

    /**
     * 检测字符串是否为email
     */
    private static function _test_email($str)
    {
        return preg_match('/^[a-z0-9]+([\+_\-\.]?[a-z0-9]+)*@([a-z0-9]+[\-]?[a-z0-9]+\.)+[a-z]{2,6}$/i', $str);
    }

    /**
     * 检测字符串是否为ip
     */
    private static function _test_ip($str)
    {
        return preg_match('/((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3}/', $str);
    }

    /**
     *  抛出异常
     */
    private static function _throw_errmsg( $msg )
    {
        throw new Exception( $msg );
    }
}

